using UnityEngine;
using System.Collections;
using System;
using System.Collections.Generic;

namespace ABA
{
	public class GoPool : UnitySingleton<GoPool> 
	{
        public class PoolTemplate
        {
            public uint num;
            public GameObject prefabTemplate;
        }
        
        private Dictionary<int, Queue<GameObject>> pools;
        private Dictionary<int, PoolTemplate> poolsTemplate;

        private GameObject poolsGameObjectParent;

        protected override void OnLoad()
        {
            InitPool();
        }

        private void InitPool()
        {
            poolsGameObjectParent = this.gameObject;
            pools = new Dictionary<int, Queue<GameObject>>();
            poolsTemplate = new Dictionary<int, PoolTemplate>();
        }

        GameObject InstGameObject(GameObject prefabTemplate)
        {
            var obj = Instantiate(prefabTemplate, Vector3.zero, Quaternion.identity);
            obj.transform.SetParent(poolsGameObjectParent.transform);
            obj.SetActive(false);

            return obj;
        }

        void ResetGameObject(GameObject obj)
        {
            obj.transform.position = Vector3.zero;
            obj.transform.rotation = Quaternion.identity;
            obj.transform.SetParent(poolsGameObjectParent.transform);
            obj.SetActive(false);
        }

        // 用模板 prefab 创建对象池，用  prefab 的 GetInstaceID 为key
        public void CreatePool(GameObject prefabTemplate, uint num)
        {
            if(num < 1)
                return;

            var instanceId = prefabTemplate.GetInstanceID();
            if(poolsTemplate.ContainsKey(instanceId)){
                PoolTemplate pt = poolsTemplate[instanceId];
                if(pt.num == num)
                    return;
                else
                    ClearPool(instanceId);
            }  

            PoolTemplate ptt = new PoolTemplate();
            ptt.num = num;
            ptt.prefabTemplate = prefabTemplate;
            poolsTemplate.Add(instanceId, ptt);

            var l = new Queue<GameObject>();
            for (int i = 0; i < num; i++)
            {
                var obj = InstGameObject(prefabTemplate);
                l.Enqueue(obj);
            }
            pools.Add(instanceId, l);
        }

        public void ClearPool(int instanceId){
            if(poolsTemplate.ContainsKey(instanceId)){
                poolsTemplate.Remove(instanceId);
                var l = pools[instanceId];

                while(true){
                    var obj = l.Dequeue();
                    GameObject.Destroy(obj);
                    if(l == null || l.Count == 0){
                        break;
                    }
                }
           
                pools.Remove(instanceId);
            }              
        }

        public Queue<GameObject> GetPool(int instanceId){
            if(poolsTemplate.ContainsKey(instanceId)){
                return pools[instanceId];
            }      

            return null;        
        }

        public int GetPoolCount(int instanceId){
            if(pools.ContainsKey(instanceId))
            {
                Queue<GameObject> pool = pools[instanceId];
                return pool.Count;
            }    

            return 0;        
        }

        // 得到对象池对象
        public GameObject Get(int instanceId)
        {
            GameObject retObj = null;
            if(pools.ContainsKey(instanceId))
            {
                Queue<GameObject> pool = pools[instanceId];
                if(pool.Count > 0){
                    retObj = pool.Dequeue();
                }
                else{
                    var pt = poolsTemplate[instanceId];
                    retObj = InstGameObject(pt.prefabTemplate);
                    pool.Enqueue(retObj);
                    retObj = pool.Dequeue();
                }
                retObj.SetActive(true);
            }
            else{
                Debug.LogError(GetType() + " Get: do not Create Pool!");
            }

            return retObj;
        }
        
        // 放回对象池对象
        public void Put(int instanceId, GameObject obj)
        {
            if(poolsGameObjectParent == null)
                return;

            if(pools.ContainsKey(instanceId))
            {
                var pool = pools[instanceId];
                ResetGameObject(obj);
                pool.Enqueue(obj);
            }
        }
	}
}

